use ash::vk::{self, TaggedStructure};

pub fn get_render_pass_ci() -> vk::RenderPassCreateInfo {
    vk::RenderPassCreateInfo { 
        s_type                  : vk::StructureType::RENDER_PASS_CREATE_INFO,
        p_next                  : std::ptr::null(), 
        flags                   : vk::RenderPassCreateFlags::empty(),
        // attachment_count        : (), 
        // p_attachments           : (), 
        // subpass_count           : (), 
        // p_subpasses             : (), 
        // dependency_count        : (), 
        // p_dependencies          : (),

        ..Default::default()
    }
}

pub fn get_framebuffer_ci() -> vk::FramebufferCreateInfo {
    vk::FramebufferCreateInfo { 
        s_type                  : vk::StructureType::FRAMEBUFFER_CREATE_INFO, 
        p_next                  : std::ptr::null(), 
        flags                   : vk::FramebufferCreateFlags::empty(), 
        // render_pass             : (), 
        // attachment_count        : (), 
        // p_attachments           : (), 
        // width                   : (), 
        // height                  : (), 
        // layers                  : () 

        ..Default::default()
    }
}

pub fn get_pipeline_ci() -> vk::GraphicsPipelineCreateInfo {
    vk::GraphicsPipelineCreateInfo { 
        s_type                      : vk::StructureType::GRAPHICS_PIPELINE_CREATE_INFO, 
        p_next                      : std::ptr::null(), 
        flags                       : vk::PipelineCreateFlags::empty(), 
        // stage_count: (), 
        // p_stages: (), 
        // p_vertex_input_state: (), 
        // p_input_assembly_state: (), 
        // p_tessellation_state: (), 
        // p_viewport_state: (), 
        // p_rasterization_state: (), 
        // p_multisample_state: (), 
        // p_depth_stencil_state: (), 
        // p_color_blend_state: (), 
        // p_dynamic_state: (), 
        // layout: (), 
        // render_pass: (), 
        // subpass: (), 
        // base_pipeline_handle: (),
        // base_pipeline_index: (),
        
        ..Default::default()
    }
}

pub fn get_pipeline_vertex_input_state_ci() -> vk::PipelineVertexInputStateCreateInfo {
    vk::PipelineVertexInputStateCreateInfo { 
        s_type                      : vk::PipelineVertexInputStateCreateInfo::STRUCTURE_TYPE, 
        p_next                      : std::ptr::null(), 
        flags                       : vk::PipelineVertexInputStateCreateFlags::empty(), 
        // vertex_binding_description_count: (), 
        // p_vertex_binding_descriptions: (), 
        // vertex_attribute_description_count: (), 
        // p_vertex_attribute_descriptions: () 
        ..Default::default()
    }
}

pub fn get_pipeline_input_assembly_state_ci() -> vk::PipelineInputAssemblyStateCreateInfo {
    vk::PipelineInputAssemblyStateCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        topology                    : vk::PrimitiveTopology::TRIANGLE_LIST,
        primitive_restart_enable    : vk::FALSE,
        ..Default::default()
    }
}

pub fn get_pipeline_tessellation_state_ci() -> vk::PipelineTessellationStateCreateInfo {
    vk::PipelineTessellationStateCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        // patch_control_points: () 
    
        ..Default::default()
    }
}

pub fn get_pipeline_viewport_state_ci() -> vk::PipelineViewportStateCreateInfo {
    vk::PipelineViewportStateCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        // viewport_count: (),
        // p_viewports: (), 
        // scissor_count: (), 
        // p_scissors: () 
    
        ..Default::default()
    }
}

pub fn get_pipeline_rasterization_state_ci() -> vk::PipelineRasterizationStateCreateInfo {
    vk::PipelineRasterizationStateCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        depth_clamp_enable: vk::FALSE, 
        rasterizer_discard_enable: vk::FALSE, 
        polygon_mode: vk::PolygonMode::FILL, 
        cull_mode: vk::CullModeFlags::NONE, 
        front_face: vk::FrontFace::CLOCKWISE, 
        depth_bias_enable: vk::FALSE, 
        depth_bias_constant_factor: 0.0f32, 
        depth_bias_clamp: 0.0f32, 
        depth_bias_slope_factor: 0.0f32, 
        line_width: 1.0f32 ,
    
        ..Default::default()
    }
}

pub fn get_pipeline_multisample_state_ci() -> vk::PipelineMultisampleStateCreateInfo {
    vk::PipelineMultisampleStateCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        rasterization_samples               : vk::SampleCountFlags::TYPE_1, 
        sample_shading_enable               : vk::FALSE, 
        min_sample_shading                  : 1.0f32, 
        // p_sample_mask: (), 
        alpha_to_coverage_enable            : vk::FALSE, 
        alpha_to_one_enable                 : vk::FALSE,
    
        ..Default::default()
    }
}

pub fn get_pipeline_depth_stencil_state_ci() -> vk::PipelineDepthStencilStateCreateInfo {
    vk::PipelineDepthStencilStateCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        // depth_test_enable: (), 
        // depth_write_enable: (), 
        // depth_compare_op: (), 
        // depth_bounds_test_enable: (), 
        // stencil_test_enable: (), 
        // front: (), 
        // back: (), 
        // min_depth_bounds: (), 
        // max_depth_bounds: () 
    
        ..Default::default()
    }
}

pub fn get_pipeline_color_blend_state_ci() -> vk::PipelineColorBlendStateCreateInfo {
    vk::PipelineColorBlendStateCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        logic_op_enable: vk::FALSE, 
        logic_op: vk::LogicOp::COPY, 
        // attachment_count: (), 
        // p_attachments: (), 
        blend_constants: [0.0f32, 0.0f32, 0.0f32, 0.0f32],

        ..Default::default()
    }
}

pub fn get_pipeline_color_blend_attachment_state() -> vk::PipelineColorBlendAttachmentState {
    vk::PipelineColorBlendAttachmentState {
        color_write_mask            : vk::ColorComponentFlags::RGBA,
        blend_enable                : vk::FALSE,
        src_color_blend_factor      : vk::BlendFactor::ONE,
        dst_color_blend_factor      : vk::BlendFactor::ZERO,
        color_blend_op              : vk::BlendOp::ADD,
        src_alpha_blend_factor      : vk::BlendFactor::ONE,
        dst_alpha_blend_factor      : vk::BlendFactor::ZERO,
        alpha_blend_op              : vk::BlendOp::ADD
    }
}

/// 默认load_op为Clear，store_op为Store
pub fn get_attachment_description() -> vk::AttachmentDescription {
    vk::AttachmentDescription {
        format                  : vk::Format::UNDEFINED,
        flags                   : vk::AttachmentDescriptionFlags::empty(),
        samples                 : vk::SampleCountFlags::TYPE_1,
        load_op                 : vk::AttachmentLoadOp::CLEAR,              // Load的时候不Clear，就会残留，并且背景没有ClearColor
        store_op                : vk::AttachmentStoreOp::STORE,
        stencil_load_op         : vk::AttachmentLoadOp::DONT_CARE,
        stencil_store_op        : vk::AttachmentStoreOp::DONT_CARE,
        initial_layout          : vk::ImageLayout::UNDEFINED,
        final_layout            : vk::ImageLayout::UNDEFINED
    }
}

pub fn get_subpass_description() -> vk::SubpassDescription {
    vk::SubpassDescription {
        flags                           : vk::SubpassDescriptionFlags::empty(),
        pipeline_bind_point             : vk::PipelineBindPoint::GRAPHICS,
        input_attachment_count          : 0,
        p_input_attachments             : std::ptr::null(),
        color_attachment_count          : 0,
        p_color_attachments             : std::ptr::null(),
        p_resolve_attachments           : std::ptr::null(),
        p_depth_stencil_attachment      : std::ptr::null(),
        preserve_attachment_count       : 0,
        p_preserve_attachments          : std::ptr::null()
    }
}

pub fn get_pipeline_dynamic_state_ci() -> vk::PipelineDynamicStateCreateInfo {
    vk::PipelineDynamicStateCreateInfo { 
        s_type:                     vk::StructureType::PIPELINE_DYNAMIC_STATE_CREATE_INFO, 
        // p_next: (), 
        // flags: (), 
        // dynamic_state_count: (), 
        // p_dynamic_states: () 
    
        ..Default::default()
    }
}

pub fn get_pipeline_shader_stage_ci() -> vk::PipelineShaderStageCreateInfo {
    vk::PipelineShaderStageCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        // stage: (), 
        // module: (), 
        // p_name: (), 
        // p_specialization_info: () 
    
        ..Default::default()
    }
}

pub fn get_pipeline_layout_ci() -> vk::PipelineLayoutCreateInfo {
    vk::PipelineLayoutCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        // set_layout_count: (), 
        // p_set_layouts: (), 
        // push_constant_range_count: (), 
        // p_push_constant_ranges: () 
    
        ..Default::default()
    }
}

pub fn get_shader_module_ci() -> vk::ShaderModuleCreateInfo {
    vk::ShaderModuleCreateInfo { 
        // s_type: (), 
        // p_next: (), 
        // flags: (), 
        // code_size: (), 
        // p_code: () 
    
        ..Default::default()
    }
}

pub fn get_submit_info() -> vk::SubmitInfo {
    vk::SubmitInfo {
        s_type                              : vk::StructureType::SUBMIT_INFO,
        p_next                              : std::ptr::null(),
        // wait_semaphore_count                : wait_semaphores.len() as u32,
        // p_wait_semaphores                   : wait_semaphores.as_ptr(),
        // p_wait_dst_stage_mask               : wait_stages.as_ptr(),
        // command_buffer_count                : command_buffer.len() as u32,
        // p_command_buffers                   : command_buffer.as_ptr(),
        // signal_semaphore_count              : signal_semaphores.len() as u32,
        // p_signal_semaphores                 : signal_semaphores.as_ptr()

        ..Default::default()
    }
}

pub fn get_render_pass_begin_info() -> vk::RenderPassBeginInfo {
    vk::RenderPassBeginInfo {
        s_type                  : vk::StructureType::RENDER_PASS_BEGIN_INFO,
        p_next                  : std::ptr::null(),
        // render_pass             : self.on_screen_render_pass,
        // framebuffer             : self.on_screen_framebuffers[image_index as usize],
        // render_area             : vk::Rect2D { offset: vk::Offset2D { x: 0, y: 0 }, extent: self.swapchain.get_extent() },
        // clear_value_count       : clear_values.len() as u32,
        // p_clear_values          : clear_values.as_ptr()

        ..Default::default()
    }
}

pub fn get_descriptor_set_layout_binding() -> vk::DescriptorSetLayoutBinding {
    vk::DescriptorSetLayoutBinding {
        ..Default::default()
    }
}

pub(crate) fn get_sampler_create_info() -> vk::SamplerCreateInfo {
    vk::SamplerCreateInfo {
        s_type                      : vk::StructureType::SAMPLER_CREATE_INFO,
        p_next                      : std::ptr::null(),
        flags                       : vk::SamplerCreateFlags::empty(),
        // mag_filter                  : vk::Filter::LINEAR,
        // min_filter                  : vk::Filter::LINEAR,
        // mipmap_mode                 : vk::SamplerMipmapMode::LINEAR,
        // address_mode_u              : vk::SamplerAddressMode::REPEAT,
        // address_mode_v              : vk::SamplerAddressMode::REPEAT,
        // address_mode_w              : vk::SamplerAddressMode::REPEAT,
        // mip_lod_bias                : 0.0f32,
        // anisotropy_enable           : 0,
        // max_anisotropy              : 0.0f32,
        // compare_enable              : vk::FALSE,
        // compare_op                  : vk::CompareOp::ALWAYS,
        // min_lod                     : 0.0f32,
        // max_lod                     : 0.0f32,
        // border_color                : vk::BorderColor::INT_OPAQUE_BLACK,
        // unnormalized_coordinates    : vk::FALSE

        ..Default::default()
    }
}

pub(crate) fn get_descriptor_set_layout_create_info() -> vk::DescriptorSetLayoutCreateInfo {
    vk::DescriptorSetLayoutCreateInfo {
        s_type      : vk::StructureType::DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
        p_next      : std::ptr::null(),
        flags       : vk::DescriptorSetLayoutCreateFlags::empty(),

        ..Default::default()
    }
}

pub(crate) fn get_descriptor_set_allocate_info() -> vk::DescriptorSetAllocateInfo {
    vk::DescriptorSetAllocateInfo {
        s_type: vk::StructureType::DESCRIPTOR_SET_ALLOCATE_INFO,
        p_next: std::ptr::null(),
        // descriptor_pool         : vk_context.vk_descriptor_pool,
        // descriptor_set_count    : 1,
        // p_set_layouts           : [descriptor_layout].as_ptr()

        ..Default::default()
    }
}

pub(crate) fn get_image_view_ci() -> vk::ImageViewCreateInfo {
    vk::ImageViewCreateInfo {
        s_type              : vk::StructureType::IMAGE_VIEW_CREATE_INFO,
        p_next              : std::ptr::null(),
        flags               : vk::ImageViewCreateFlags::empty(),
        // image               :
        // view_type           :
        // format              :
        // components          : VkComponentMapping structure specifying a remapping of color components
        // subresource_range   : VkImageSubresourceRange structure selecting the set of mipmap levels and array layers to be accessible to the view

        ..Default::default()
    }
}

pub(crate) fn get_image_create_info() -> vk::ImageCreateInfo {
    vk::ImageCreateInfo {
        s_type          : vk::StructureType::IMAGE_CREATE_INFO,
        p_next          : std::ptr::null(),
        // flags,
        // image_type,
        // format,
        // extent,
        // mip_levels,
        // array_layers,
        // samples,
        // tiling,
        // usage,
        // sharing_mode,
        // queue_family_index_count,
        // p_queue_family_indices,
        // initial_layout,

        ..Default::default()
    }
}

pub(crate) fn get_memory_allocate_info() -> vk::MemoryAllocateInfo {
    vk::MemoryAllocateInfo {
        s_type                  : vk::StructureType::MEMORY_ALLOCATE_INFO,
        p_next                  : std::ptr::null(),
        // allocation_size,
        // memory_type_index,

        ..Default::default()
    }
}

pub(crate) fn get_buffer_create_info() -> vk::BufferCreateInfo {
    vk::BufferCreateInfo {
        s_type                  : vk::StructureType::BUFFER_CREATE_INFO,
        p_next                  : std::ptr::null(),

        ..Default::default()
    }
}